package logger

import (
	"errors"
	"fmt"
	"log/slog"
	"slices"
	"strings"
)

type Level slog.Level

var (
	levelNames = make(map[slog.Level]string, 6) // 已注册的日志等级levelAgent, 预留两个自定义容量
	levelKeys  = make([]slog.Level, 0, 6)       // 已注册的日志等级排序后的Level索引
)
var (
	LevelDebug = slog.LevelDebug
	LevelInfo  = slog.LevelInfo
	LevelWarn  = slog.LevelWarn
	LevelError = slog.LevelError
)

func init() {
	// 自动注册 slog 默认的4个预定义日志等级
	levelNames[slog.LevelDebug] = "DEBUG"
	levelNames[slog.LevelInfo] = "INFO"
	levelNames[slog.LevelWarn] = "WARN"
	levelNames[slog.LevelError] = "ERROR"
	levelKeys = append(levelKeys, slog.LevelDebug, slog.LevelInfo, slog.LevelWarn, slog.LevelError)
}

// RegisterLevel 注册一个自定义的日志等级(全局可用，仅需注册一次)
//   - level: 日志等级
//   - name: 日志等级名称
//   - slog内置 slog.Level(LevelDebug < LevelInfo < LevelWarn < LevelError)
//   - Use:
//   - LevelTrace = slog.Level(-8) // < LevelDebug
//   - LevelFatal = slog.Level(12) // > LevelError
//   - 例: RegisterLevel(slog.Level(16),"PANIC") 注册后，可以直接使用 slog.Level(16)
func RegisterLevel(level slog.Level, name string) error {
	logInstanceMu.Lock()
	defer logInstanceMu.Unlock()
	l := level.Level()
	if _, ok := levelNames[l]; ok {
		return errors.New("logger.LevelRegister: level val already exists")
	}
	name = strings.ToUpper(strings.TrimSpace(name))
	if name == "" {
		return errors.New("logger.LevelRegister: level name cannot be empty")
	}
	for _, n := range levelNames {
		if n == name {
			return errors.New("logger.LevelRegister: level name already exists")
		}
	}
	levelNames[l] = name
	levelKeys = append(levelKeys, l)
	slices.Sort(levelKeys)
	return nil
}
func (l Level) Level() slog.Level {
	return slog.Level(l)
}
func (l Level) String() string {
	level := slog.Level(l)
	if name, ok := levelNames[level]; ok {
		return name
	}
	str := func(base string, val slog.Level) string {
		if val == 0 {
			return base
		}
		return fmt.Sprintf("%s%+d", base, val)
	}
	for _, l := range levelKeys {
		if level < l {
			return str(levelNames[l], level-l)
		}
	}
	return str(levelNames[levelKeys[len(levelKeys)-1]], level-levelKeys[len(levelKeys)-1])
}

// GetRegisterLevels 获取全局已注册的日志等级列表(包含 slog 默认4个日志等级)，按从日志等级从低到高的顺序排序
func GetRegisterLevels() []struct {
	Level slog.Level
	Name  string
} {
	var levels []struct {
		Level slog.Level
		Name  string
	}
	for _, l := range levelKeys {
		levels = append(levels, struct {
			Level slog.Level
			Name  string
		}{l, levelNames[l]})
	}
	return levels
}

// ConvertLevelString 将日志等级字符串转换为 slog.Level
//   - 支持 Slog 标准Level 和 全局自定义日志等级字符串转换
//   - 返回 False 表示未找到匹配的日志等级字符串
func ConvertLevelString(s string) (slog.Level, bool) {
	s = strings.ToUpper(s)
	for level, str := range levelNames {
		if s == str {
			return level, true
		}
	}
	return 0, false
}
